home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1998 July / EnigmA AMIGA RUN 29 (1998)(G.R. Edizioni)(IT)[!][issue 1998-07 & 08].iso / earcd / grafica / flashmandel / sources / modules / iff.c < prev    next >
C/C++ Source or Header  |  1998-02-02  |  54KB  |  1,891 lines

  1. /******************************************************************************
  2. **
  3. **  Coded by Dino Papararo 02-Feb-1998
  4. **
  5. **  Based on NewIff package relased by Commodore
  6. **
  7. **  FUNCTION
  8. **
  9. **    QueryMandPic -- Examine an IFF picture.
  10. **
  11. **  SYNOPSIS
  12. **
  13. **    LONG QueryMandPic (struct ILBMInfo *,struct MandelChunk **,UBYTE *);
  14. **
  15. **  DESCRIPTION
  16. **
  17. **    Passed an initilized ILBMInfo with a not-in-use IFFHandle, a MandelChunk
  18. **
  19. **    structure and a filename, will open an ILBM, fill in ilbm->camg and
  20. **
  21. **    ilbm->bmhd, and close the ILBM.
  22. **
  23. **    This allows you to determine if the ILBM is a size and
  24. **
  25. **    type you want to deal with.
  26. **
  27. **    For succes is necessary the ID_MAND into the iff file !
  28. **
  29. **    Returns 0 for success or an IFFERR (libraries/iffparse.h).
  30. **
  31. **
  32. **  FUNCTION
  33. **
  34. **    LoadMandPic -- Load an IFF picture.
  35. **
  36. **  SYNOPSIS
  37. **
  38. **    LONG LoadMandPic (struct ILBMInfo *,UBYTE *);
  39. **
  40. **  DESCRIPTION
  41. **
  42. **    Function uses a ILBMInfo struct with record ParseInfo.iff initialized
  43. **
  44. **    with AllocIFF() function, and a pointer to a FileName.
  45. **
  46. **    It's necessary a valid Window RPort and ViewPort initialized in the passed
  47. **
  48. **    ILBM Structure for the BODY and COLORS, at end all memory will be freed.
  49. **
  50. **
  51. **  FUNCTION
  52. **
  53. **    SaveMandPic -- save a screen as IFF picture.
  54. **
  55. **  SYNOPSIS
  56. **
  57. **    LONG SaveMandPic (struct ILBMInfo *,struct Chunk *,struct Chunk *,UBYTE *);
  58. **
  59. **  DESCRIPTION
  60. **
  61. **    Function uses a ILBMInfo struct with record ParseInfo.iff initialized
  62. **
  63. **    with AllocIFF() function, two custom chunks, and a pointer to a FileName.
  64. **
  65. **    In the 1st custom chunk I put the copyright infos and in the 2nd the
  66. **
  67. **    special chunk MAND used for window limits, fractal limits, iterations
  68. **
  69. **    type...
  70. **
  71. **    Function will save the icon file too with support for NewIcons.
  72. **
  73. ******************************************************************************/
  74.  
  75. #define INTUI_V36_NAMES_ONLY
  76. #define __USE_SYSBASE
  77.  
  78.  
  79. #include <proto/intuition.h>
  80. #include <proto/graphics.h>
  81. #include <proto/icon.h>
  82. #include <proto/iffparse.h>
  83. #include <proto/wb.h>
  84.  
  85. #include <exec/types.h>
  86. #include <intuition/intuitionbase.h>
  87. #include <intuition/screens.h>
  88. #include <graphics/gfxbase.h>
  89. #include <workbench/workbench.h>
  90.  
  91. #include <iffp/ilbm.h>
  92. #include <iffp/ilbmapp.h>
  93. #include <iffp/iff.h>
  94. #include <iffp/packer.h>
  95. #include <iffp/iffpstrings.h>
  96.  
  97. UBYTE *omodes [2] = {"r","w"};
  98.  
  99. static BYTE *PutDump(BYTE *,int);
  100.  
  101. static BYTE *PutRun(BYTE *,int,int);
  102.  
  103. #define MaxSrcPlanes (25)
  104.  
  105. #define ID_MAND MAKE_ID('M','A','N','D')
  106.  
  107. #define NOMAND 4L
  108.  
  109. #define DUMP    0
  110. #define RUN    1
  111. #define MinRun 3
  112. #define MaxRun 128
  113. #define MaxDat 128
  114. #define INBUFSZ 128
  115. #define BODYBUFSZ    5004
  116. #define GetByte()       (*source++)
  117. #define PutByte(c)      { *dest++ = (c);   ++PackPutSize; }
  118. #define OutDump(nn)     dest = PutDump(dest, nn)
  119. #define OutRun(nn,cc)   dest = PutRun(dest, nn, cc)
  120. #define UGetByte()    (*source++)
  121. #define UPutByte(c)    (*dest++ = (c))
  122.  
  123. /* local function prototypes */
  124.  
  125. struct  CatCompArrayType CatCompArray [8];
  126.  
  127. LONG QueryMandPic (struct ILBMInfo *,struct MandelChunk **,UBYTE *filename);
  128.  
  129. LONG LoadMandPic (struct ILBMInfo *,UBYTE *);
  130.  
  131. LONG SaveMandPic (struct ILBMInfo *,struct Chunk *,struct Chunk *,UBYTE *);
  132.  
  133. LONG SavePalette (struct ILBMInfo *,struct Chunk *,UBYTE *);
  134.  
  135. LONG LoadPalette (struct ILBMInfo *,UBYTE *);
  136.  
  137. static LONG __saveds __asm stdio_stream (register __a0 struct Hook *,register __a2 struct IFFHandle *,register __a1 struct IFFStreamCmd *);
  138.  
  139. LONG saveilbm (struct ILBMInfo *,struct BitMap *,ULONG,WORD,WORD,WORD,WORD,APTR,UWORD,UWORD,WORD,WORD,struct Chunk *,struct Chunk *,UBYTE *);
  140.  
  141. LONG initbmhd (BitMapHeader *,struct BitMap *,WORD,WORD,WORD,WORD,WORD,WORD,WORD,ULONG);
  142.  
  143. LONG loadcmap (struct ILBMInfo *);
  144.  
  145. LONG putcmap (struct IFFHandle *,APTR,UWORD,UWORD);
  146.  
  147. LONG loadbody (struct IFFHandle *,struct BitMap *,BitMapHeader *);
  148.  
  149. LONG loadbody2 (struct IFFHandle *,struct BitMap *,BYTE *,BitMapHeader *,BYTE *,ULONG);
  150.  
  151. LONG putbody (struct IFFHandle *,struct BitMap *,BYTE *,BitMapHeader *,BYTE *,LONG);
  152.  
  153. ULONG getcamg (struct ILBMInfo *);
  154.  
  155. LONG openifile (struct ParseInfo *,UBYTE *,ULONG);
  156.  
  157. LONG parseifile (struct    ParseInfo *,LONG,LONG,LONG *,LONG *,LONG *);
  158.  
  159. VOID closeifile (struct ParseInfo *);
  160.  
  161. VOID initiffasstdio (struct IFFHandle *);
  162.  
  163. LONG PutCk (struct IFFHandle *,LONG,LONG,VOID *);
  164.  
  165. LONG getcolors (struct ILBMInfo *);
  166.  
  167. LONG alloccolortable (struct ILBMInfo *);
  168.  
  169. LONG setcolors (struct ILBMInfo *,struct ViewPort *);
  170.  
  171. VOID freecolors (struct ILBMInfo *);
  172.  
  173. LONG chkcnt (LONG *);
  174.  
  175. LONG getcontext (struct IFFHandle *);
  176.  
  177. LONG contextis (struct IFFHandle *,LONG,LONG);
  178.  
  179. LONG currentchunkis (struct IFFHandle *,LONG,LONG);
  180.  
  181. UBYTE *findpropdata (struct IFFHandle *,LONG,LONG);
  182.  
  183. static BYTE *PutDump (BYTE *,int);
  184.  
  185. static BYTE *PutRun (BYTE *,int,int);
  186.  
  187. LONG PackRow (BYTE **,BYTE **,LONG);
  188.  
  189. BOOL UnPackRow (BYTE **,BYTE **,WORD,WORD);
  190.  
  191. LONG PackPutSize;
  192.  
  193. char PackBuffer [256];    /* [TBD] should be 128?  on stack?*/
  194.  
  195. /* Data for project icon for saved ILBM */
  196.  
  197. UWORD ILBMI1Data [] =
  198. {
  199.   /* Plane 0*/
  200.   0x0000,0x0000,0x0000,0x0001,0x7fff,0xffff,0xffff,0xffff,  0x1fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,
  201.   0x7fff,0xffff,0xffff,0xffff,0x3fff,0xffff,0xffff,0xffff,  0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffdf,0xffff,
  202.   0x7fff,0xffff,0xffff,0x7fff,0x7fff,0xffff,0xffff,0x7fff,  0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,
  203.   0x7fff,0xffff,0xfdff,0xbfff,0x7fff,0xffff,0xfdff,0xffff,  0x7fff,0xffff,0xf7ff,0xfbff,0x7fff,0xffff,0xffff,0xffff,
  204.   0x7fff,0xffff,0xffff,0xffbf,0x7fff,0xfffe,0x7fff,0xffff,  0x7fff,0xfffe,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,
  205.   0x7fff,0xfffd,0xffff,0xffef,0x7fff,0xffff,0xffff,0xffcf,  0x7fff,0xffff,0xffff,0xffdf,0x7fff,0xee3f,0xffff,0xffff,
  206.   0x7fff,0xffdf,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x7fff,0xfff7,0xffff,0xffff,0x7fff,0x7ff3,0xffff,0xffff,
  207.   0x7ffb,0xffff,0xffff,0xffff,0x7ffe,0xffff,0xffff,0xffff,  0x6b7f,0xffff,0xffff,0xffff,0x7ffb,0xffff,0xffff,0xffff,
  208.   0x7fff,0xfff3,0xffff,0xffff,0x7fff,0xfff7,0xffff,0xffff,  0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffef,0xffff,0xffff,
  209.   0x7fff,0xffdf,0xffff,0xffff,0x7fff,0xdfff,0xffff,0xffdf,  0x7fff,0xfdff,0xffff,0xffdf,0x7fff,0xffff,0xffff,0xffff,
  210.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x7fff,0xfffe,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,
  211.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xfdff,  0x7fff,0xffff,0xf7ff,0xfbbf,0x7fff,0xffff,0xcfff,0xffff,
  212.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffee,0xffff,  0x7fff,0xffff,0xffff,0x7fff,0x7fff,0xffff,0xffff,0x7fff,
  213.   0x7fff,0xffff,0xffff,0x7fff,0x7fff,0xffff,0xffcf,0xffff,  0x7fff,0xffff,0xfffd,0xffff,0x3fff,0xffff,0xffff,0xffff,
  214.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x5fff,0xffff,0xffff,0xffff,0x1fff,0xffff,0xffff,0xffff,
  215.   0x4fff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  216.   /* Plane 1*/
  217.   0xffff,0xffff,0xffff,0xfffe,0xcfff,0xffff,0xffff,0xfffe,  0xffff,0xffff,0xffff,0x7ffe,0xbfff,0xffff,0xffff,0xfffe,
  218.   0xffff,0xffff,0xffff,0xfffe,0xffff,0xffff,0xffff,0xfffe,  0xbfff,0xffff,0xfffb,0xfffe,0xffff,0xffff,0xffc1,0xfffe,
  219.   0xffff,0xffff,0xffe0,0x7ffe,0xffff,0xffff,0xffe0,0x7ffe,  0xffff,0xffff,0xffe1,0xfffe,0xffff,0xffff,0xfff3,0xfffe,
  220.   0xffff,0xffff,0xfdc0,0x3ffe,0xffff,0xffff,0xdc00,0x07fe,  0xffff,0xffff,0xc400,0x03fe,0xffff,0xffff,0xe000,0x003e,
  221.   0xffff,0xffff,0xc000,0x003e,0xffff,0xfffe,0x4000,0x007e,  0xffff,0xfffe,0x0000,0x007e,0xffff,0xffff,0x0000,0x003e,
  222.   0xffff,0xfffc,0x0000,0x000e,0xffff,0xfffe,0x0000,0x000e,  0xffff,0xddfc,0x0000,0x001e,0xffff,0xc83c,0x0000,0x001e,
  223.   0xffff,0xc01c,0x0000,0x001e,0xffff,0xc01c,0x0000,0x003e,  0xffff,0x8004,0x0000,0x003e,0xffff,0x0000,0x0000,0x003e,
  224.   0xfffb,0x0004,0x0000,0x003e,0xfff8,0x0000,0x0000,0x007e,  0xa360,0x0000,0x0000,0x01fe,0xfff9,0x0000,0x0000,0x003e,
  225.   0xffff,0x0000,0x0000,0x003e,0xffff,0x8004,0x0000,0x003e,  0xffff,0x800c,0x0000,0x001e,0xffff,0xc00c,0x0000,0x001e,
  226.   0xffff,0xc01c,0x0000,0x001e,0xffff,0xddfc,0x0000,0x001e,  0xffff,0xfdfe,0x0000,0x001e,0xffff,0xfffe,0x0000,0x001e,
  227.   0xffff,0xffff,0x0000,0x003e,0xffff,0xffff,0x0000,0x003e,  0xffff,0xfffe,0x0000,0x007e,0xffff,0xffff,0xc000,0x00fe,
  228.   0xffff,0xffff,0xe000,0x003e,0xffff,0xffff,0xc000,0x003e,  0xffff,0xffff,0xc400,0x023e,0xffff,0xffff,0xcc00,0x07fe,
  229.   0xffff,0xffff,0xfff1,0xfffe,0xffff,0xffff,0xffe0,0xfffe,  0xffff,0xffff,0xffe0,0x7ffe,0xffff,0xffff,0xffe0,0x7ffe,
  230.   0xffff,0xffff,0xffe0,0x7ffe,0xffff,0xffff,0xffc1,0xfffe,  0xffff,0xffff,0xfff9,0xfffe,0xffff,0xffff,0xffff,0xfffe,
  231.   0xbfff,0xffff,0xffff,0xfffe,0xffff,0xffff,0xffff,0xfffe,  0xffff,0xffff,0xffff,0xfffe,0xffff,0xffff,0xffd7,0xfffe,
  232.   0xffff,0xffff,0xffff,0xfffe,0x0000,0x0000,0x0000,0x0000
  233. };
  234.  
  235. UWORD ILBMI2Data [] =
  236. {
  237.   /* Plane 0*/
  238.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xfffe,  0x9ddd,0xdddd,0xdddd,0xdddc,0xffff,0xffff,0xffff,0xfffe,
  239.   0xf777,0x7777,0x7777,0x7776,0xbfff,0xffff,0xffff,0xfffe,  0xdddd,0xdddd,0xdddd,0xdddc,0xffff,0xffff,0xffc3,0xfffe,
  240.   0xf777,0x7777,0x7775,0x7776,0xffff,0xffff,0xffe8,0x7ffe,  0xdddd,0xdddd,0xddd5,0xdddc,0xffff,0xffff,0xfff3,0xfffe,
  241.   0xf777,0x7777,0x7555,0x3776,0xffff,0xffff,0xdc88,0x8ffe,  0xdddd,0xdddd,0xd555,0x51dc,0xffff,0xffff,0xe222,0x223e,
  242.   0xf777,0x7777,0x5555,0x5536,0xffff,0xfffe,0x4888,0x88fe,  0xdddd,0xdddc,0x5555,0x555c,0xffff,0xffff,0x2222,0x223e,
  243.   0xf777,0x7775,0x5555,0x5546,0xffff,0xfffe,0x8888,0x888e,  0xdddd,0xdddd,0x5555,0x555c,0xffff,0xea3e,0x2222,0x223e,
  244.   0xf777,0x5555,0x5555,0x5556,0xffff,0xc89c,0x8888,0x88be,  0xdddd,0xd555,0x5555,0x555c,0xffff,0x2222,0x2222,0x223e,
  245.   0xf773,0x5555,0x5555,0x5576,0xfff8,0x8888,0x8888,0x88fe,  0xc955,0x5555,0x5555,0x55dc,0xfffb,0x2222,0x2222,0x223e,
  246.   0xf777,0x5551,0x5555,0x5576,0xffff,0x8884,0x8888,0x88be,  0xdddd,0xd55d,0x5555,0x555c,0xffff,0xe22e,0x2222,0x223e,
  247.   0xf777,0x5555,0x5555,0x5556,0xffff,0xddfc,0x8888,0x889e,  0xdddd,0xdddd,0x5555,0x555c,0xffff,0xfffe,0x2222,0x223e,
  248.   0xf777,0x7777,0x5555,0x5576,0xffff,0xffff,0x8888,0x88be,  0xdddd,0xdddc,0x5555,0x555c,0xffff,0xffff,0xe222,0x22fe,
  249.   0xf777,0x7777,0x7555,0x5576,0xffff,0xffff,0xc888,0x88be,  0xdddd,0xdddd,0xd555,0x511c,0xffff,0xffff,0xce22,0x27fe,
  250.   0xf777,0x7777,0x7775,0x7776,0xffff,0xffff,0xffe8,0xfffe,  0xdddd,0xdddd,0xddd5,0x5ddc,0xffff,0xffff,0xffe2,0x7ffe,
  251.   0xf777,0x7777,0x7775,0x7776,0xffff,0xffff,0xffc9,0xfffe,  0xdddd,0xdddd,0xdddd,0xdddc,0xbfff,0xffff,0xffff,0xfffe,
  252.   0xf777,0x7777,0x7777,0x7776,0xffff,0xffff,0xffff,0xfffe,  0xdddd,0xdddd,0xdddd,0xdddc,0x9fff,0xffff,0xffff,0xfffe,
  253.   0xc777,0x7777,0x7777,0x7776,0x0000,0x0000,0x0000,0x0000,
  254.   /* Plane 1*/
  255.   0x0000,0x0000,0x0000,0x0000,0x4fff,0xffff,0xffff,0xffff,  0x7fff,0xffff,0xffff,0x7fff,0x3fff,0xffff,0xffff,0xffff,
  256.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x3fff,0xffff,0xfffb,0xffff,0x7fff,0xffff,0xffdd,0xffff,
  257.   0x7fff,0xffff,0xffea,0x7fff,0x7fff,0xffff,0xfff7,0x7fff,  0x7fff,0xffff,0xffeb,0xffff,0x7fff,0xffff,0xffff,0xffff,
  258.   0x7fff,0xffff,0xfdea,0xbfff,0x7fff,0xffff,0xfd77,0x77ff,  0x7fff,0xffff,0xe6aa,0xabff,0x7fff,0xffff,0xfddd,0xddff,
  259.   0x7fff,0xffff,0xeaaa,0xaabf,0x7fff,0xfffe,0x7777,0x777f,  0x7fff,0xfffe,0xaaaa,0xaaff,0x7fff,0xffff,0xdddd,0xddff,
  260.   0x7fff,0xfffc,0xaaaa,0xaaaf,0x7fff,0xffff,0x7777,0x774f,  0x7fff,0xfffe,0xaaaa,0xaa9f,0x7fff,0xcc3d,0xdddd,0xdddf,
  261.   0x7fff,0xea9e,0xaaaa,0xaabf,0x7fff,0xf77f,0x7777,0x777f,  0x7fff,0xaaa6,0xaaaa,0xaabf,0x7fff,0x5dd1,0xdddd,0xddff,
  262.   0x7ffb,0xaaae,0xaaaa,0xaabf,0x7ffe,0x7777,0x7777,0x777f,  0x236a,0xaaaa,0xaaaa,0xabff,0x7ff9,0xdddd,0xdddd,0xddff,
  263.   0x7fff,0xaaa2,0xaaaa,0xaabf,0x7fff,0xf777,0x7777,0x777f,  0x7fff,0xaaae,0xaaaa,0xaabf,0x7fff,0xddcd,0xdddd,0xdddf,
  264.   0x7fff,0xea9e,0xaaaa,0xaabf,0x7fff,0xdfff,0x7777,0x775f,  0x7fff,0xfdfe,0xaaaa,0xaa9f,0x7fff,0xffff,0xdddd,0xdddf,
  265.   0x7fff,0xffff,0xaaaa,0xaabf,0x7fff,0xffff,0x7777,0x777f,  0x7fff,0xfffe,0xaaaa,0xaaff,0x7fff,0xffff,0xdddd,0xddff,
  266.   0x7fff,0xffff,0xeaaa,0xaabf,0x7fff,0xffff,0xf777,0x757f,  0x7fff,0xffff,0xe6aa,0xaabf,0x7fff,0xffff,0xcddd,0xdfff,
  267.   0x7fff,0xffff,0xfffb,0xffff,0x7fff,0xffff,0xffe6,0xffff,  0x7fff,0xffff,0xffea,0x7fff,0x7fff,0xffff,0xfffd,0x7fff,
  268.   0x7fff,0xffff,0xffea,0x7fff,0x7fff,0xffff,0xffc7,0xffff,  0x7fff,0xffff,0xfff9,0xffff,0x7fff,0xffff,0xffff,0xffff,
  269.   0x3fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffd7,0xffff,
  270.   0x7fff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
  271. };
  272.  
  273. struct Image ILBMI1 =
  274. {
  275.     0,0,           /* Upper left corner */
  276.     64,62,2,       /* Width, Height, Depth */
  277.     ILBMI1Data,    /* Image data */
  278.     0x0004,0x0000, /* PlanePick, PlaneOnOff */
  279.     NULL           /* Next image */
  280. };
  281.  
  282. struct Image ILBMI2 =
  283. {
  284.     0,0,           /* Upper left corner */
  285.     64,62,2,       /* Width, Height, Depth */
  286.     ILBMI2Data,    /* Image data */
  287.     0x0004,0x0000, /* PlanePick, PlaneOnOff */
  288.     NULL           /* Next image */
  289. };
  290.  
  291. UBYTE *ILBMTools [] =
  292. {
  293.   "FILETYPE=ILBM",
  294.   
  295.   /* NewIcons tooltypes for NewIcons icon */
  296.   
  297.   "*** DON'T EDIT THE FOLLOWING LINES!! ***",
  298.   "IM1=BEI!*£»5#<@¸®®¢;¤9n1(dFJ«¡!m9Ó&TBÇÑ",
  299.   "IM1=ÛdBá(g[®(ß(ÈdB.ÅÞ(Éc9m(ZÝ(ÉS$B6T=Û1(ÉPeJ¦(«.`Ù1¿ÉP¦DB2¥M'@×\"1Â(P¥dS9hj6c¡Ö\"=Á·P¥fW[­·E+A¹Õ\">0²(¥fÈ[®¿Ä2e¡ÅÔ\">,²J¥fÈ[®¿ÈYiB¹",
  300.   "IM1=ZÓ\">,1I(fÈ[®¿È[­µ¢T=Ò\">,5I,·È[®¿È[®·E+A¹Ñ\">,51-¿È[®¿È[®¿RH«.`\">,51m¿È[®¿È[®¿Ä2e¡Å\">,51®¿È[®¿È[®¿Ä2e¡ÅÑ!/&*h·È[®¿È[®¿ÈYiB¹ZÒg",
  301.   "IM1=c%DC[®¿È[®¿È[lj6c¡ÒC²b¦1l¿È[®¿È[­µ¢T=Ó1Á²*hdW[®¿È[®·E+A¹Ó(ÉS%J£;®¿È[®·E+A¹Ô$\\Ab1I-¿È[®·E+A¹Õ\"=Á·P¥fW[­·E+A¹Ö!(Éd8JB9lµE+A¹Ø$",
  302.   "IM1=[¯,5I(d¦+A¹ÁØ\"1/&(¦J¢+A¹1[`Ø.gc8B1SA¹1(e±Ö!¿1C³,·TA¹1(dNÖ=³1(¢À(d=¹1(e¿Õ#­B1(dHg[®(1(®±Õ[dB1(dB1B1\"1+­Õ'XdB1(dB1(dB1[`Õ'(dB",
  303.   "IM1=(dB1(dB1+­×<B1(dB1(dB1[`Ø.Â(dB1(dB7XÛ[dB1(dBÈÝ!¿1(dNÁß'Xe¿â=±ñ",
  304.   "IM2=BEI!-£»5#<@¸®®¢;¤9n1(d9l·VS9ll¦U@#:RS9l±Ò!m(®`Ö",
  305.   "IM2=ÛdBÞ*¦J¦J¦I(Û!J¦JÈ(eJ¦DÚ)D®¿Â!(dUE£Ù5D¦¿È((dB:£»`×5D®³1!+®¿È5IU@Ö5D¦¿1((®¿ÈY*¥«¡Õ)D®³\"1+­dB1,ÆJM0Ô!D¦¿,1(®µB1(¸J¦6hÓ!D®³,·[",
  306.   "IM2=[hfS9n¦J¦J¥`Ò!J®³,·[­dS9lÆJ¦IUJ@Òj­@L·S(fZ¦J¦J¦J¥«®0Ñ*®³\"·S8dS¦J¦J¦J¦J¦ºÒ¥@BÇS9fZ¦J¦J¦J¦JMNhÑEB\"7S9lS¦J¦J¦J¦J¦JÅ`EHBÈ39l»¦J",
  307.   "IM2=¦J¦J¦J¦E¦0Ñ$¡e¿FS9¦J¦J¦J¦J¦J¦NhÑ%B\"7S9l´¦J¦J¦J¦J¦JÅ`ÑJ¡1[ªlS=J¦J¦J¦J¦J7DÒ5X`enB1,ÆJ¦J¦J¦J¢Z@Ñ!Jd$NÃ1(¸J¦J¦J¦J¢Z@Ó¦¿01[®µC9l",
  308.   "IM2=9»¦JMNhÓ!J­@BÈ[hfS9n¦:MNhÕ¥¿Â!(e¿B1(g:¦JhÕ\"JW((dNÃ1(dZ¦Fi@Õ!5K­B01[®¿Ë¤2¤A¦Ö*¦B1!+®À:¦1iI(f`ÖJ¦[d$UJ¦Jhµ¥dTÖJb:¦J¦JMF¦DRJ¥Õ%",
  309.   "IM2=¦$B1(e)J¥»UJC:`Ô*¡dB1(dB4B0U:¦9m@Ò!J(dB1(dB1(dB:¦Jl·¡Ñ!A(dB1(dB1(dCJ%2¦FSHÑ*(dB1(dB1(dU@Ñ2iJ¤9lÑ%HB1(dB1(f¥Ó)D¦Ia@Ò5A(dB1(»",
  310.   "IM2=¡Ô!4j¦J`Ó5A(dCJ×jEJhÕ¦$U@ØE2hÖ\"¥Ú2iDâ)D¡Ó",
  311.   NULL
  312. };
  313.  
  314. struct DiskObject ILBMobject =
  315. {
  316.   WB_DISKMAGIC,                      /* Magic Number */
  317.   WB_DISKVERSION,                    /* Version */
  318.   {                                  /* Embedded Gadget Structure */
  319.     NULL,                            /* Next Gadget Pointer */
  320.     0, 0, 64, 62,                    /* Left,Top,Width,Height */
  321.     GFLG_GADGIMAGE | GADGBACKFILL,   /* Flags */
  322.     GACT_RELVERIFY | GACT_IMMEDIATE, /* Activation Flags */
  323.     GTYP_BOOLGADGET,                 /* Gadget Type */
  324.     (APTR)&ILBMI1,                   /* Render Image */
  325.     (APTR)&ILBMI2,                   /* Select Image */
  326.     NULL,                            /* Text for Gadget*/
  327.     NULL,                            /* Mutual Exclude */
  328.     NULL,                            /* Special Info */
  329.     0,                               /* Gadget ID */
  330.     NULL                             /* User Data */
  331.   },
  332.   WBPROJECT,                        /* Icon Type */
  333.   "MultiView",                      /* Default Tool */
  334.   ILBMTools,                        /* Tool Type Array */
  335.   NO_ICON_POSITION,                 /* Current X */
  336.   NO_ICON_POSITION,                 /* Current Y */
  337.   NULL,                             /* Drawer Structure */
  338.   NULL,                             /* Tool Window */
  339.   NULL                              /* Stack Size */
  340. };
  341.  
  342. struct MandelChunk { WORD LeftEdge,TopEdge,Width,Height;
  343.                      long double RMin,RMax,IMin,IMax;
  344.                      long double RConst,IConst;
  345.                      ULONG Iterations;
  346.                      ULONG Special;
  347.                    };
  348.  
  349. /* saveilbm
  350.  *
  351.  * Given an ILBMInfo with a currently available (not-in-use)
  352.  *   ParseInfo->iff IFFHandle, a BitMap ptr, modeid, widths/heights,
  353.  *   colortable, ncolors, bitspergun, masking, transparent color,
  354.  *   optional chunklists, and filename, will save the bitmap as an ILBM.
  355.  *
  356.  *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
  357.  *  if bitspergun=8,  colortable is byte guns of RGBRGB etc. (like a CMAP)
  358.  *  if bitspergun=32, colortable is ULONG guns of RGBRGB etc.
  359.  *     Only the high eight bits of each gun will be written to CMAP.
  360.  *     Four bit guns n will be saved as nn
  361.  *
  362.  * The struct Chunk *chunklist is for chunks you wish written
  363.  * other than BMHD, CMAP, and CAMG (they will be screened out)
  364.  * because they are calculated and written separately
  365.  *
  366.  * Returns 0 for success, or an IFFERR
  367.  */
  368.  
  369. LONG saveilbm (struct ILBMInfo *ilbm,struct BitMap *bitmap,
  370.                ULONG modeid,WORD width,WORD height,WORD pagewidth,WORD pageheight,
  371.                APTR colortable,UWORD ncolors,UWORD bitspergun,
  372.                WORD masking,WORD transparentColor,
  373.                struct Chunk *chunklist1,struct Chunk *chunklist2,
  374.                UBYTE *filename)
  375. {
  376. struct IFFHandle *iff;
  377.  
  378. struct Chunk *chunk;
  379.  
  380. ULONG chunkID;
  381.  
  382. UBYTE *bodybuf;
  383.  
  384. LONG size, error;
  385.  
  386.   iff = ilbm->ParseInfo.iff;
  387.  
  388.   if (! (modeid & 0xFFFF0000)) modeid &= OLDCAMGMASK;
  389.  
  390.   if (! (bodybuf = AllocVec (BODYBUFSZ,MEMF_PUBLIC))) return (IFFERR_NOMEM);
  391.  
  392.   error = openifile (&(ilbm->ParseInfo), filename, IFFF_WRITE);
  393.  
  394.   if (! error)
  395.   {
  396.     error = PushChunk (iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN);
  397.  
  398.     initbmhd (&ilbm->Bmhd, bitmap, masking, cmpByteRun1, transparentColor, width, height, pagewidth, pageheight, modeid);
  399.  
  400.     CkErr (putbmhd (iff,&ilbm->Bmhd));
  401.  
  402.     if (colortable) CkErr (putcmap (iff,colortable,ncolors,bitspergun));
  403.  
  404.     if (ilbm->IFFPFlags & IFFPF_NOMONITOR) modeid &= (~MONITOR_ID_MASK);
  405.  
  406.     ilbm->camg = modeid;
  407.  
  408.     CkErr (putcamg (iff,&modeid));
  409.  
  410.     /* Write out chunklists 1 & 2 (if any), except for
  411.  
  412.      * any BMHD, CMAP, or CAMG (computed/written separately) */
  413.  
  414.     for (chunk = chunklist1; chunk; chunk = chunk->ch_Next)
  415.     {
  416.       chunkID = chunk->ch_ID;
  417.  
  418.       if ((chunkID != ID_BMHD) && (chunkID != ID_CMAP) && (chunkID != ID_CAMG))
  419.       {
  420.         size = chunk->ch_Size == IFFSIZE_UNKNOWN ? strlen (chunk->ch_Data) : chunk->ch_Size;
  421.  
  422.         CkErr (PutCk (iff, chunkID, size, chunk->ch_Data));
  423.       }
  424.     }
  425.  
  426.     for (chunk = chunklist2; chunk; chunk = chunk->ch_Next)
  427.     {
  428.       chunkID = chunk->ch_ID;
  429.  
  430.       if ((chunkID != ID_BMHD) && (chunkID != ID_CMAP) && (chunkID != ID_CAMG))
  431.       {
  432.         size = chunk->ch_Size == IFFSIZE_UNKNOWN ? strlen (chunk->ch_Data) : chunk->ch_Size;
  433.  
  434.         CkErr (PutCk (iff, chunkID, size, chunk->ch_Data));
  435.       }
  436.     }
  437.  
  438.     /* Write out the BODY */
  439.  
  440.     CkErr (putbody (iff, bitmap, NULL, &ilbm->Bmhd, bodybuf, BODYBUFSZ));
  441.  
  442.     CkErr (PopChunk (iff));    /* close out the FORM */
  443.  
  444.     closeifile (&(ilbm->ParseInfo));    /* and the file */
  445.   }
  446.  
  447.   FreeVec (bodybuf);
  448.  
  449.   return (error);
  450. }
  451.  
  452. /* openifile
  453.  *
  454.  * Passed a ParseInfo structure with a not-in-use IFFHandle, filename
  455.  *   and IFF open mode (IFFF_READ or IFFF_WRITE) opens file for use with
  456.  *   iffparse.library support modules.
  457.  *
  458.  * Returns 0 for success or an IFFERR (libraries/iffparse.h)
  459.  */
  460.  
  461. LONG openifile (struct ParseInfo *pi, UBYTE *filename, ULONG iffopenmode)
  462. {
  463. struct IFFHandle *iff;
  464.  
  465. LONG error = CLIENT_ERROR;
  466.  
  467.   if (! pi) return (error);
  468.  
  469.   if (! (iff = pi->iff)) return (error);
  470.  
  471.   pi->clipboard = FALSE;
  472.  
  473.   /* Set up IFFHandle for buffered stdio I/O. */
  474.  
  475.   if (! (iff->iff_Stream = (ULONG) fopen (filename,omodes [iffopenmode & 1]))) return (NOFILE);
  476.  
  477.   else initiffasstdio (iff);
  478.  
  479.   pi->filename = filename;
  480.  
  481.   error = OpenIFF (iff,iffopenmode);
  482.  
  483.   pi->opened = error ? FALSE : TRUE;    /* currently open handle */
  484.  
  485.   return (error);
  486. }
  487.  
  488. /* closeifile
  489.  *
  490.  * closes file or clipboard opened with openifile, and frees all
  491.  *   iffparse context parsed by parseifile.
  492.  *
  493.  */
  494.  
  495. void closeifile (struct ParseInfo *pi)
  496. {
  497. struct IFFHandle *iff;
  498.  
  499.   if (! pi) return;
  500.  
  501.   if (! (iff = pi->iff)) return;
  502.  
  503.   if (pi->opened) CloseIFF (iff);
  504.  
  505.   if (iff->iff_Stream)
  506.   {
  507.     if (pi->clipboard) CloseClipboard ((struct ClipboardHandle *) (iff->iff_Stream));
  508.  
  509.     else fclose ((FILE *) (iff->iff_Stream));
  510.   }
  511.  
  512.   iff->iff_Stream = NULL;
  513.  
  514.   pi->clipboard = NULL;
  515.  
  516.   pi->opened = NULL;
  517. }
  518.  
  519. /*
  520.  * File I/O hook functions which the IFF library will call.
  521.  * A return of 0 indicates success (no error).
  522.  *
  523.  * Iffparse.library calls this code via struct Hook and Hook.asm
  524.  */
  525. static LONG __saveds __asm stdio_stream (register __a0 struct Hook *hook,register __a2 struct IFFHandle *iff,register __a1 struct IFFStreamCmd *actionpkt)
  526. {
  527. register FILE *stream;
  528. register LONG nbytes;
  529. register LONG actual;
  530. register UBYTE *buf;
  531. LONG len;
  532.  
  533.   stream = (FILE *) iff->iff_Stream;
  534.  
  535.   if (! stream) return (1L);
  536.  
  537.   nbytes = actionpkt->sc_NBytes;
  538.  
  539.   buf = (UBYTE *) actionpkt->sc_Buf;
  540.  
  541.   switch (actionpkt->sc_Command)
  542.   {
  543.     case IFFSCC_READ: do
  544.                       {  actual = (nbytes > 32767 ? 32767 : nbytes);
  545.  
  546.                          if ((len = fread (buf, 1, actual, stream)) != actual) break;
  547.  
  548.                          nbytes -= actual;
  549.  
  550.                          buf += actual;
  551.  
  552.                       } while (nbytes > NULL);
  553.  
  554.                       return (nbytes ? IFFERR_READ : NULL);
  555.  
  556.     case IFFSCC_WRITE: do
  557.                        {  actual = (nbytes > 32767 ? 32767 : nbytes);
  558.  
  559.                           if ((len = fwrite (buf, 1, actual, stream)) != actual) break;
  560.  
  561.                           nbytes -= actual;
  562.  
  563.                           buf += actual;
  564.  
  565.                        } while (nbytes > NULL);
  566.  
  567.                        return (nbytes ? IFFERR_WRITE : NULL);
  568.  
  569.     case IFFSCC_SEEK:  return ((fseek (stream, nbytes, 1) == -1) ? IFFERR_SEEK : NULL);
  570.  
  571.     default:           return (NULL);  /*  No _INIT or _CLEANUP required.  */
  572.   }
  573. }
  574.  
  575. /* initiffasstdio (ie. init iff as stdio)
  576.  *
  577.  * sets up hook callback for the file stream handler above
  578.  */
  579.  
  580. void initiffasstdio (struct IFFHandle *iff)
  581. {
  582. static struct Hook stdiohook = {{NULL},(ULONG (*)()) stdio_stream,NULL,NULL};
  583.  
  584. /*
  585.  * Initialize the IFF structure to point to the buffered I/O
  586.  * routines.  Unbuffered I/O is terribly slow.
  587.  */
  588.  
  589.   InitIFF (iff, IFFF_FSEEK | IFFF_RSEEK, &stdiohook);
  590. }
  591.  
  592. /* PutCk
  593.  * Writes one chunk of data to an iffhandle
  594.  */
  595.  
  596. LONG PutCk (struct IFFHandle *iff,long id,long size,void *data)
  597. {
  598. LONG error,wlen;
  599.  
  600.   if (! (error = PushChunk (iff,0,id,size)))
  601.   {
  602.      /* Write the actual data */
  603.  
  604.      if ((wlen = WriteChunkBytes (iff,data,size)) != size) error = IFFERR_WRITE;
  605.  
  606.      else error = PopChunk (iff);
  607.   }
  608.  
  609.   return (error);
  610. }
  611.  
  612. /*---------- initbmhd -------------------------------------------------*/
  613.  
  614. LONG initbmhd (BitMapHeader *bmhd, struct BitMap *bitmap,
  615.                WORD masking, WORD compression, WORD transparentColor,
  616.                WORD width, WORD height, WORD pageWidth, WORD pageHeight,
  617.                ULONG modeid)
  618. {
  619.   struct DisplayInfo DI;
  620.  
  621.   if ((! bmhd) || (! bitmap) || (! width) || (! height)) return (CLIENT_ERROR);
  622.  
  623.   bmhd->w = width;
  624.  
  625.   bmhd->h = height;
  626.  
  627.   bmhd->x = bmhd->y = 0;    /* Default position is (0,0).*/
  628.  
  629.   bmhd->nPlanes = bitmap->Depth;
  630.  
  631.   bmhd->masking = masking;
  632.  
  633.   bmhd->compression = compression;
  634.  
  635.   bmhd->flags = BMHDF_CMAPOK;    /* we will store 8 significant bits */
  636.  
  637.   bmhd->transparentColor = transparentColor;
  638.  
  639.   bmhd->pageWidth = pageWidth;
  640.  
  641.   bmhd->pageHeight = pageHeight;
  642.  
  643.   bmhd->xAspect = 0;    /* So we can tell when we've got it */
  644.  
  645.   if (GetDisplayInfoData (NULL, (UBYTE *) &DI, sizeof (struct DisplayInfo), DTAG_DISP, modeid))
  646.   {
  647.      bmhd->xAspect = DI.Resolution.x;
  648.  
  649.      bmhd->yAspect = DI.Resolution.y;
  650.   }
  651.  
  652.     /* If running under 1.3 or GetDisplayInfoData failed, use old method
  653.      * of guessing aspect ratio */
  654.  
  655.   if (! bmhd->xAspect)
  656.   {
  657.     bmhd->xAspect =  44;
  658.  
  659.     bmhd->yAspect = ((struct GfxBase *) GfxBase)->DisplayFlags & PAL ? 44 : 52;
  660.  
  661.     if (modeid & HIRES) bmhd->xAspect = bmhd->xAspect >> 1;
  662.  
  663.     if (modeid & LACE)  bmhd->yAspect = bmhd->yAspect >> 1;
  664.   }
  665.  
  666.   return (IFF_OKAY);
  667. }
  668.  
  669. /*---------- putcmap ---------------------------------------------------*/
  670. /*  This function will accept a table of color values in one of the
  671.  *  following forms:
  672.  *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
  673.  *  if bitspergun=8,  colortable is bytes of RGBRGB etc. (like a CMAP)
  674.  *  if bitspergun=32, colortable is ULONGS of RGBRGB etc.
  675.  *  (only the high eight bits of each gun will be written to CMAP)
  676.  */
  677.  
  678. LONG putcmap (struct IFFHandle *iff,APTR colortable,UWORD ncolors,UWORD bitspergun)
  679. {
  680. LONG error, offs;
  681.  
  682. WORD  *tabw;
  683.  
  684. UBYTE *tab8;
  685.  
  686. ColorRegister cmapReg;
  687.  
  688.   if ((! iff) || (! colortable)) return (CLIENT_ERROR);
  689.  
  690.   /* size of CMAP is 3 bytes * ncolors */
  691.  
  692.   if (error = PushChunk (iff,NULL,ID_CMAP,ncolors * sizeofColorRegister)) return (error);
  693.  
  694.   if (bitspergun == 4)
  695.   {
  696.     /* Store each 4-bit value n as nn */
  697.  
  698.     tabw = (UWORD *) colortable;
  699.  
  700.     for (; ncolors; --ncolors)
  701.     {
  702.       cmapReg.red    = ( *tabw >> 4 ) & 0xf0;
  703.  
  704.       cmapReg.red   |= (cmapReg.red >> 4);
  705.  
  706.       cmapReg.green  = ( *tabw      ) & 0xf0;
  707.  
  708.       cmapReg.green |= (cmapReg.green >> 4);
  709.  
  710.       cmapReg.blue   = ( *tabw << 4 ) & 0xf0;
  711.  
  712.       cmapReg.blue  |= (cmapReg.blue >> 4);
  713.  
  714.       if ((WriteChunkBytes (iff,(BYTE *) &cmapReg,sizeofColorRegister)) != sizeofColorRegister) return (IFFERR_WRITE);
  715.  
  716.       ++tabw;
  717.     }
  718.   }
  719.  
  720.   else
  721.  
  722.     if ((bitspergun == 8) || (bitspergun == 32))
  723.     {
  724.       tab8 = (UBYTE *) colortable;
  725.  
  726.       offs = (bitspergun == 8) ? 1 : 4;
  727.  
  728.       for ( ;  ncolors;  --ncolors )
  729.       {
  730.         cmapReg.red   = *tab8;
  731.  
  732.         tab8 += offs;
  733.  
  734.         cmapReg.green = *tab8;
  735.  
  736.         tab8 += offs;
  737.  
  738.         cmapReg.blue  = *tab8;
  739.  
  740.         tab8 += offs;
  741.  
  742.         if ((WriteChunkBytes (iff,(BYTE *) &cmapReg,sizeofColorRegister)) != sizeofColorRegister) return (IFFERR_WRITE);
  743.       }
  744.     }
  745.  
  746.   error = PopChunk (iff);
  747.  
  748.   return (error);
  749. }
  750.  
  751. /*---------- putbody ---------------------------------------------------*/
  752. /* NOTE: This implementation could be a LOT faster if it used more of the
  753.  * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
  754.  * therefore to DOS Write).
  755.  *
  756.  * Incorporates modification by Jesper Steen Moller to accept source
  757.  * rows wider than dest rows, with one modulo variable for source bitplane
  758.  * rows and one for the ILBM bitmap rows.
  759.  */
  760.  
  761. LONG putbody (struct IFFHandle *iff, struct BitMap *bitmap, BYTE *mask,BitMapHeader *bmhd, BYTE *buffer, LONG bufsize)
  762. {
  763. LONG error;
  764.  
  765. LONG rowBytes = bitmap->BytesPerRow;   /* for source modulo only */
  766.  
  767. LONG FileRowBytes = RowBytes (bmhd->w); /* width to write in bytes */
  768.  
  769. int dstDepth = bmhd->nPlanes;
  770.  
  771. UBYTE compression = bmhd->compression;
  772.  
  773. int planeCnt;                          /* number of bit planes including mask */
  774.  
  775. register int iPlane, iRow;
  776.  
  777. register LONG packedRowBytes;
  778.  
  779. BYTE *buf;
  780.  
  781. BYTE *planes [MAXSAVEDEPTH + 1];        /* array of ptrs to planes & mask */
  782.  
  783.   if ( bufsize < MaxPackedSize (FileRowBytes) ||  /* Must buffer a comprsd row*/
  784.  
  785.        compression > cmpByteRun1              ||  /* bad arg */
  786.  
  787.        bitmap->Rows != bmhd->h                ||  /* inconsistent */
  788.  
  789.        rowBytes < FileRowBytes                ||  /* inconsistent*/
  790.  
  791.        bitmap->Depth < dstDepth               ||  /* inconsistent */
  792.  
  793.        dstDepth > MAXSAVEDEPTH )                  /* too many for this routine*/
  794.  
  795.     return (CLIENT_ERROR);
  796.  
  797.   planeCnt = dstDepth + (mask == NULL ? 0 : 1);
  798.  
  799.   /* Copy the ptrs to bit & mask planes into local array "planes" */
  800.  
  801.   for (iPlane = 0; iPlane < dstDepth; iPlane++) planes [iPlane] = (BYTE *) bitmap->Planes [iPlane];
  802.  
  803.   if (mask != NULL) planes [dstDepth] = mask;
  804.  
  805.   /* Write out a BODY chunk header */
  806.  
  807.   if (error = PushChunk (iff, NULL, ID_BODY, IFFSIZE_UNKNOWN)) return (error);
  808.  
  809.   /* Write out the BODY contents */
  810.  
  811.   for (iRow = bmhd->h; iRow > 0; iRow--)
  812.   {
  813.     for (iPlane = 0; iPlane < planeCnt; iPlane++)
  814.     {
  815.       /* Write next row.*/
  816.  
  817.       if (compression == cmpNone)
  818.       {
  819.         if (WriteChunkBytes (iff,planes [iPlane],FileRowBytes) != FileRowBytes) error = IFFERR_WRITE;
  820.  
  821.         planes [iPlane] += rowBytes; /* Possibly skipping unused bytes */
  822.       }
  823.  
  824.       else                     /* Compress and write next row.*/
  825.       {
  826.         buf = buffer;
  827.  
  828.         packedRowBytes = PackRow (&planes [iPlane], &buf, FileRowBytes);
  829.  
  830.         /* Note that packrow incremented planes already by FileRowBytes */
  831.  
  832.         planes [iPlane] += rowBytes-FileRowBytes; /* Possibly skipping unused bytes */
  833.  
  834.         if (WriteChunkBytes (iff,buffer,packedRowBytes) != packedRowBytes) error = IFFERR_WRITE;
  835.       }
  836.  
  837.       if (error) return (error);
  838.     }
  839.   }
  840.  
  841.   /* Finish the chunk */
  842.  
  843.   error = PopChunk (iff);
  844.  
  845.   return (error);
  846. }
  847.  
  848. LONG loadcmap (struct ILBMInfo *ilbm)
  849. {
  850. struct StoredProperty *sp;
  851.  
  852. struct IFFHandle *iff;
  853.  
  854. BOOL AllShifted;
  855.  
  856. UBYTE *rgb, rb, gb, bb;
  857.  
  858. LONG k;
  859.  
  860. ULONG ncolors, gun, ncheck, nc, r, g, b;
  861.  
  862.   if (! (iff = ilbm->ParseInfo.iff)) return (CLIENT_ERROR);
  863.  
  864.   if (! (ilbm->colortable)) return (1L);
  865.  
  866.   if (! (sp = FindProp (iff, ID_ILBM, ID_CMAP))) return (1L);
  867.  
  868.   rgb = sp->sp_Data;
  869.  
  870.   /* file has this many colors */
  871.  
  872.   nc = sp->sp_Size / sizeofColorRegister;
  873.  
  874.   ncolors = nc;
  875.  
  876.   /* if ILBMInfo can't hold that many, we'll load less */
  877.  
  878.   if (ilbm->ncolors < ncolors) ncolors = ilbm->ncolors;
  879.  
  880.   /* set to how many we are loading */
  881.  
  882.   ilbm->ncolors = ncolors;
  883.  
  884.   /* how many colors to check for shifted nibbles (i.e. used colors) */
  885.  
  886.   ncheck = 1L << ilbm->Bmhd.nPlanes;
  887.  
  888.   if (ncheck > ncolors) ncheck = ncolors;
  889.  
  890.   if ((! (ilbm->IFFPFlags & IFFPF_NOCOLOR32)) && (ilbm->colorrecord))
  891.   {
  892.     ilbm->colorrecord [0] = ncolors << 16L;
  893.  
  894.     /* Assign to 32-bit table, examine for all-shifted nibbles at same time */
  895.  
  896.     AllShifted = TRUE;
  897.  
  898.     k = 0;
  899.  
  900.     while (ncheck--)
  901.     {
  902.       ilbm->colortable32 [k].r = rb = *rgb++;
  903.  
  904.       ilbm->colortable32 [k].g = gb = *rgb++;
  905.  
  906.       ilbm->colortable32 [k].b = bb = *rgb++;
  907.  
  908.       if (((rb & 0x0F) || (gb & 0x0F) || (bb & 0x0F))) AllShifted = FALSE;
  909.  
  910.       k++;
  911.     }
  912.  
  913.     /* If no file/user indication that this is an 8-bit significant CMAP... */
  914.  
  915.     if ((! (ilbm->IFFPFlags & IFFPF_CMAPOK)) &&    (! (ilbm->Bmhd.flags & BMHDF_CMAPOK)))
  916.     {
  917.       /* If all nibbles appear shifted (4 bit), duplicate the nibbles */
  918.  
  919.       if (AllShifted)
  920.       {
  921.         for (k = 0; k < nc; k++)
  922.         {
  923.           ilbm->colortable32 [k].r |= (ilbm->colortable32 [k].r >> 4);
  924.  
  925.           ilbm->colortable32 [k].g |= (ilbm->colortable32 [k].g >> 4);
  926.  
  927.           ilbm->colortable32 [k].b |= (ilbm->colortable32 [k].b >> 4);
  928.         }
  929.       }
  930.     }
  931.  
  932.     /* Now scale to 32 bits */
  933.  
  934.     for (k = 0; k < nc; k++)
  935.     {
  936.       gun = ilbm->colortable32 [k].r;
  937.  
  938.       ilbm->colortable32 [k].r |= ((gun << 24) | (gun << 16) | (gun << 8));
  939.  
  940.       gun = ilbm->colortable32 [k].g;
  941.  
  942.       ilbm->colortable32 [k].g |= ((gun << 24) | (gun << 16) | (gun << 8));
  943.  
  944.       gun = ilbm->colortable32 [k].b;
  945.  
  946.       ilbm->colortable32 [k].b |= ((gun << 24) | (gun << 16) | (gun << 8));
  947.     }
  948.   }
  949.  
  950.   /* always make old-style table */
  951.  
  952.   rgb = sp->sp_Data;
  953.  
  954.   ncolors = nc;
  955.  
  956.   k = 0;
  957.  
  958.   while (ncolors--)
  959.   {
  960.     r = (*rgb++ & 0xF0) << 4;
  961.  
  962.     g = *rgb++ & 0xF0;
  963.  
  964.     b = *rgb++ >> 4;
  965.  
  966.     ilbm->colortable [k] = r | g | b;
  967.  
  968.     k++;
  969.   }
  970.  
  971.   return (NULL);
  972. }
  973.  
  974. LONG getcolors (struct ILBMInfo *ilbm)
  975. {
  976. struct IFFHandle *iff;
  977.  
  978. LONG error = CLIENT_ERROR;
  979.  
  980.   if (! (iff = ilbm->ParseInfo.iff)) return (error);
  981.  
  982.   if (! (error = alloccolortable (ilbm))) error = loadcmap (ilbm);
  983.  
  984.   if (error) freecolors (ilbm);
  985.  
  986.   return (error);
  987. }
  988.  
  989. /* alloccolortable - allocates ilbm->colortable and sets ilbm->ncolors
  990.  *    to the number of colors we have room for in the table.
  991.  *
  992.  * V39 and above: unless ilbm->IFFPFlags & IFFPF_NOCOLOR32, will also
  993.  *  allocate and build a 32-bit per gun colortable (ilbm->colortable32)
  994.  *  and ilbm->colorrecord for LoadRGB32()
  995.  */
  996.  
  997. LONG alloccolortable (struct ILBMInfo *ilbm)
  998. {
  999. struct IFFHandle *iff;
  1000.  
  1001. struct StoredProperty *sp;
  1002.  
  1003. LONG error = NULL;
  1004.  
  1005. ULONG ctabsize;
  1006.  
  1007. UWORD ncolors;
  1008.  
  1009.   if (! (iff = ilbm->ParseInfo.iff)) return (CLIENT_ERROR);
  1010.  
  1011.   if (sp = FindProp (iff,ID_ILBM,ID_CMAP))
  1012.   {
  1013.      /*
  1014.       * Compute the size table we need
  1015.       */
  1016.  
  1017.      ncolors = sp->sp_Size / 3;        /* how many in CMAP */
  1018.  
  1019.      ncolors = MAX (ncolors,16);    /* alloc at least 16 */
  1020.  
  1021.      ctabsize = ncolors * sizeof (Color4);
  1022.  
  1023.      if (ilbm->colortable = (Color4 *) AllocVec (ctabsize,MEMF_PUBLIC | MEMF_CLEAR))
  1024.      {
  1025.     ilbm->ncolors = ncolors;
  1026.  
  1027.     ilbm->ctabsize = ctabsize;
  1028.  
  1029.         if ((! (ilbm->IFFPFlags & IFFPF_NOCOLOR32)))
  1030.     {
  1031.            ctabsize = (ncolors * sizeof (Color32)) + (2 * sizeof (LONG));
  1032.  
  1033.        if (ilbm->colorrecord = (ULONG *) AllocVec (ctabsize,MEMF_PUBLIC | MEMF_CLEAR))
  1034.            {
  1035.           ilbm->crecsize = ctabsize;
  1036.  
  1037.           ilbm->colortable32 = (Color32 *) (&ilbm->colorrecord [1L]);
  1038.  
  1039.           ilbm->colorrecord [0L] = ncolors << 16L;     /* For LoadRGB32 */
  1040.  
  1041.               ilbm->colorrecord [ncolors * sizeof (Color32) + 1L] = NULL;
  1042.            }
  1043.  
  1044.            else error = IFFERR_NOMEM;
  1045.         }
  1046.      }
  1047.  
  1048.      else error = IFFERR_NOMEM;
  1049.   }
  1050.  
  1051.   if (error) freecolors (ilbm);
  1052.  
  1053.   return (error);
  1054. }
  1055.  
  1056. VOID freecolors (struct ILBMInfo *ilbm)
  1057. {
  1058.    if (ilbm->colortable) FreeVec (ilbm->colortable);
  1059.  
  1060.    ilbm->colortable = NULL;
  1061.  
  1062.    ilbm->ctabsize = 0;
  1063.  
  1064.    if (ilbm->colorrecord) FreeVec (ilbm->colorrecord);
  1065.  
  1066.    ilbm->colorrecord  = NULL;
  1067.  
  1068.    ilbm->colortable32 = NULL;
  1069.  
  1070.    ilbm->crecsize = 0;
  1071. }
  1072.  
  1073. LONG currentchunkis (struct IFFHandle *iff,LONG type,LONG id)
  1074. {
  1075. register struct ContextNode *cn;
  1076.  
  1077. LONG result = 0;
  1078.  
  1079.   if (cn = CurrentChunk (iff))
  1080.  
  1081.     if ((cn->cn_Type == type) && (cn->cn_ID == id)) result = 1;
  1082.  
  1083.   return (result);
  1084. }
  1085.  
  1086. /*---------- loadbody ---------------------------------------------------*/
  1087.  
  1088. LONG loadbody (struct IFFHandle *iff,struct BitMap *bitmap,BitMapHeader *bmhd)
  1089. {
  1090. BYTE *buffer;
  1091.  
  1092. ULONG bufsize;
  1093.  
  1094. LONG error = 1L;
  1095.  
  1096.   if (! (currentchunkis (iff,ID_ILBM,ID_BODY))) return (IFF_OKAY);
  1097.  
  1098.   if ((bitmap) && (bmhd))
  1099.   {
  1100.      bufsize = MaxPackedSize (RowBytes (bmhd->w)) << 4L;
  1101.  
  1102.      if (! (buffer = AllocVec (bufsize,0L))) return (IFFERR_NOMEM);
  1103.  
  1104.      error = loadbody2 (iff,bitmap,NULL,bmhd,buffer,bufsize);
  1105.  
  1106.      FreeVec (buffer);
  1107.   }
  1108.  
  1109.   return (error);
  1110. }
  1111.  
  1112. LONG loadbody2 (struct IFFHandle *iff,struct BitMap *bitmap,BYTE *mask,BitMapHeader *bmhd,BYTE *buffer,ULONG bufsize)
  1113. {
  1114. UBYTE srcPlaneCnt = bmhd->nPlanes;   /* Haven't counted for mask plane yet*/
  1115.  
  1116. WORD srcRowBytes = RowBytes (bmhd->w);
  1117.  
  1118. WORD destRowBytes = bitmap->BytesPerRow;   /* used as a modulo only */
  1119.  
  1120. LONG bufRowBytes = MaxPackedSize (srcRowBytes);
  1121.  
  1122. WORD nRows = bmhd->h;
  1123.  
  1124. WORD destWidthBytes;            /* used for width check */
  1125.  
  1126. WORD compression = bmhd->compression;
  1127.  
  1128. register WORD iPlane, iRow, nEmpty;
  1129.  
  1130. register WORD nFilled;
  1131.  
  1132. BYTE *buf, *nullDest, *nullBuf, **pDest;
  1133.  
  1134. BYTE *planes [MaxSrcPlanes]; /* array of ptrs to planes & mask */
  1135.  
  1136. struct ContextNode *cn;
  1137.  
  1138.    cn = CurrentChunk (iff);
  1139.  
  1140.    if (compression > cmpByteRun1) return (CLIENT_ERROR);
  1141.  
  1142.    /* If >=V39, this may be an interleaved bitmap with a BytesPerRow
  1143.     * which is truly just a modulo and actually includes ALL planes.
  1144.     * So instead, for bounds checking, we use the pixel width of
  1145.     * the BitMap rounded up to nearest WORD, since saved ILBMs
  1146.     * are always saved as their width rounded up to nearest WORD.
  1147.     */
  1148.  
  1149.    destWidthBytes = RowBytes (GetBitMapAttr (bitmap,BMA_WIDTH));
  1150.  
  1151.    /* Complain if client asked for a conversion GetBODY doesn't handle.*/
  1152.  
  1153.    if (srcRowBytes > destWidthBytes || bufsize < (bufRowBytes * 2) || srcPlaneCnt > MaxSrcPlanes) return (CLIENT_ERROR);
  1154.  
  1155.    if (nRows > bitmap->Rows) nRows = bitmap->Rows;
  1156.  
  1157.    /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
  1158.  
  1159.    for (iPlane = 0; iPlane < bitmap->Depth; iPlane++) planes [iPlane] = (BYTE *) bitmap->Planes [iPlane];
  1160.  
  1161.    for ( ; iPlane < MaxSrcPlanes; iPlane++) planes [iPlane] = NULL;
  1162.  
  1163.    /* Copy any mask plane ptr into corresponding "planes" slot.*/
  1164.  
  1165.    if (bmhd->masking == mskHasMask)
  1166.    {
  1167.       if (mask) planes [srcPlaneCnt] = mask;  /* If there are more srcPlanes than
  1168.  
  1169.                                                * dstPlanes, there will be NULL plane-pointers before this. */
  1170.  
  1171.       else  planes [srcPlaneCnt] = NULL;  /* In case more dstPlanes than src. */
  1172.  
  1173.       srcPlaneCnt += 1;  /* Include mask plane in count.*/
  1174.    }
  1175.  
  1176.    /* Setup a sink for dummy destination of rows from unwanted planes.*/
  1177.  
  1178.    nullDest = buffer;
  1179.  
  1180.    buffer  += srcRowBytes;
  1181.  
  1182.    bufsize -= srcRowBytes;
  1183.  
  1184.    /* Read the BODY contents into client's bitmap.
  1185.     * De-interleave planes and decompress rows.
  1186.     * MODIFIES: Last iteration modifies bufsize.*/
  1187.  
  1188.    buf = buffer + bufsize;  /* Buffer is currently empty.*/
  1189.  
  1190.    for (iRow = nRows; iRow > 0; iRow--)
  1191.    {
  1192.        for (iPlane = 0; iPlane < srcPlaneCnt; iPlane++)
  1193.        {
  1194.          pDest = &planes [iPlane];
  1195.  
  1196.             /* Establish a sink for any unwanted plane.*/
  1197.  
  1198.             if (*pDest == NULL)
  1199.             {
  1200.             nullBuf = nullDest;
  1201.  
  1202.                 pDest   = &nullBuf;
  1203.             }
  1204.  
  1205.             /* Read in at least enough bytes to uncompress next row.*/
  1206.  
  1207.             nEmpty  = buf - buffer;      /* size of empty part of buffer.*/
  1208.  
  1209.             nFilled = bufsize - nEmpty;      /* this part has data.*/
  1210.  
  1211.         if (nFilled < bufRowBytes)
  1212.             {
  1213.             /* Need to read more.*/
  1214.             /* Move the existing data to the front of the buffer.*/
  1215.             /* Now covers range buffer[0]..buffer[nFilled-1].*/
  1216.  
  1217.                 movmem (buf,buffer,nFilled);  /* Could be moving 0 bytes.*/
  1218.  
  1219.                 if (nEmpty > ChunkMoreBytes (cn))
  1220.         {
  1221.                        /* There aren't enough bytes left to fill the buffer.*/
  1222.  
  1223.                      nEmpty = ChunkMoreBytes (cn);
  1224.  
  1225.                        bufsize = nFilled + nEmpty;  /* heh-heh */
  1226.                    }
  1227.  
  1228.             /* Append new data to the existing data.*/
  1229.  
  1230.                 if (ReadChunkBytes (iff,&buffer [nFilled],nEmpty) < nEmpty) return (CLIENT_ERROR);
  1231.  
  1232.                 buf = buffer;
  1233.  
  1234.             nFilled = bufsize;
  1235.             }
  1236.  
  1237.          /* Copy uncompressed row to destination plane.*/
  1238.  
  1239.             if (compression == cmpNone)
  1240.             {
  1241.                 if (nFilled < srcRowBytes)  return (IFFERR_MANGLED);
  1242.  
  1243.             movmem (buf,*pDest,srcRowBytes);
  1244.  
  1245.             buf    += srcRowBytes;
  1246.  
  1247.                 *pDest += destRowBytes;
  1248.             }
  1249.  
  1250.         else
  1251.             {
  1252.              /* Decompress row to destination plane.*/
  1253.  
  1254.                 if (UnPackRow (&buf,pDest,nFilled,srcRowBytes)) return (IFFERR_MANGLED);
  1255.  
  1256.                            /*  pSource, pDest, srcBytes, dstBytes  */
  1257.  
  1258.             else *pDest += (destRowBytes - srcRowBytes);
  1259.  
  1260.             }
  1261.     }
  1262.    }
  1263.  
  1264.    return (IFF_OKAY);
  1265. }
  1266.  
  1267. ULONG getcamg (struct ILBMInfo *ilbm)
  1268. {
  1269. struct IFFHandle *iff;
  1270.  
  1271. struct StoredProperty *sp;
  1272.  
  1273. UWORD wide,high,deep;
  1274.  
  1275. ULONG modeid = NULL;
  1276.  
  1277.   if (! (iff = ilbm->ParseInfo.iff)) return (NULL);
  1278.  
  1279.   wide = ilbm->Bmhd.pageWidth;
  1280.  
  1281.   high = ilbm->Bmhd.pageHeight;
  1282.  
  1283.   deep = ilbm->Bmhd.nPlanes;
  1284.  
  1285.   /* Grab CAMG's idea of the viewmodes */
  1286.  
  1287.   if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
  1288.   {
  1289.      modeid = (* (ULONG *) sp->sp_Data);
  1290.  
  1291.      /* knock bad bits out of old-style 16-bit viewmode CAMGs */
  1292.  
  1293.      if ((! (modeid & MONITOR_ID_MASK)) || ((modeid & EXTENDED_MODE) && (! (modeid & 0xFFFF0000)))) modeid &= (~(EXTENDED_MODE | SPRITES | GENLOCK_AUDIO | GENLOCK_VIDEO | VP_HIDE));
  1294.  
  1295.      /* check for bogus CAMG like DPaintII brushes
  1296.       * with junk in upper word and extended bit
  1297.       * not set in lower word.
  1298.       */
  1299.  
  1300.      if ((modeid & 0xFFFF0000) && (! (modeid & 0x00001000))) sp = NULL;
  1301.   }
  1302.  
  1303.   if (! sp)
  1304.   {
  1305.      /*
  1306.       * No CAMG (or bad CAMG) present; use computed modes.
  1307.       */
  1308.  
  1309.      modeid = NULL;        /* added in 39.6 */
  1310.  
  1311.      if (wide >= 640) modeid = HIRES;
  1312.  
  1313.      if (high >= 400) modeid |= LACE;
  1314.  
  1315.      if (deep == 6)
  1316.      {
  1317.         modeid |= ilbm->EHB ? EXTRA_HALFBRITE : HAM;
  1318.      }
  1319.   }
  1320.  
  1321.   if (ilbm->IFFPFlags & IFFPF_NOMONITOR) modeid &= (~MONITOR_ID_MASK);
  1322.  
  1323.   return (modeid);
  1324. }
  1325.  
  1326. LONG chkcnt (LONG *TaggedArray)
  1327. {
  1328. LONG k = 0;
  1329.  
  1330.   while (TaggedArray [k] != TAG_END) k++;
  1331.  
  1332.   return (k >> 1);
  1333. }
  1334.  
  1335. LONG getcontext (struct IFFHandle *iff)
  1336. {
  1337. LONG error;
  1338.  
  1339.   /* Based on our parse initialization, ParseIFF() will return on a stop chunk
  1340.    * (error = 0) or end of context for an ILBM FORM (error = IFFERR_EOC) or end of
  1341.    * file (error = IFFERR_EOF)
  1342.    */
  1343.  
  1344.   return (error = ParseIFF (iff,IFFPARSE_SCAN));
  1345. }
  1346.  
  1347. LONG parseifile (struct    ParseInfo *pi,LONG groupid,LONG grouptype,LONG *propchks,LONG *collectchks,LONG *stopchks)
  1348. {
  1349. struct IFFHandle *iff;
  1350.  
  1351. register struct ContextNode *cn;
  1352.  
  1353. LONG error;
  1354.  
  1355.   if (! (iff = pi->iff)) return (CLIENT_ERROR);
  1356.  
  1357.   if (! iff->iff_Stream) return (IFFERR_READ);
  1358.  
  1359.   pi->hunt = FALSE;
  1360.  
  1361.   /* Declare property, collection and stop chunks.*/
  1362.  
  1363.   if (propchks)
  1364.  
  1365.       if (error = PropChunks (iff, propchks, chkcnt (propchks))) return (error);
  1366.  
  1367.   if (collectchks)
  1368.  
  1369.           if (error = CollectionChunks (iff, collectchks, chkcnt (collectchks))) return (error);
  1370.  
  1371.   if (stopchks)
  1372.  
  1373.           if (error = StopChunks (iff, stopchks, chkcnt (stopchks))) return (error);
  1374.  
  1375.     /* We want to stop at the end of an ILBM context. */
  1376.  
  1377.   if (grouptype)
  1378.  
  1379.       if (error = StopOnExit (iff, grouptype, groupid)) return (error);
  1380.  
  1381.     /* Take first parse step to enter main chunk. */
  1382.  
  1383.   if (error = ParseIFF (iff,IFFPARSE_STEP)) return (error);
  1384.  
  1385.     /* Test the chunk info to see if simple form of type we want (ILBM).*/
  1386.  
  1387.   if (! (cn = CurrentChunk (iff))) return (NOFILE); /* This really should never happen.  If it does, it means our parser is broken. */
  1388.  
  1389.   if (cn->cn_ID != groupid || cn->cn_Type != grouptype) pi->hunt = TRUE; /* Warning - this is a complex file */
  1390.  
  1391.   if (! error) error = getcontext (iff);
  1392.  
  1393.   return (error);
  1394. }
  1395.  
  1396. LONG contextis (struct IFFHandle *iff,LONG type,LONG id)
  1397. {
  1398. register struct ContextNode *cn;
  1399.  
  1400. LONG result = NULL;
  1401.  
  1402.   if (cn = (CurrentChunk (iff)))
  1403.   {
  1404.     if (cn = (ParentChunk (cn)))
  1405.     {
  1406.       if ((cn->cn_Type == type) && (cn->cn_ID == id)) result = 1L;
  1407.     }
  1408.   }
  1409.  
  1410.   return (result);
  1411. }
  1412.  
  1413. UBYTE *findpropdata (struct IFFHandle *iff,LONG type,LONG id)
  1414. {
  1415. register struct StoredProperty *sp;
  1416.  
  1417.   if (sp = FindProp (iff,type,id)) return (sp->sp_Data);
  1418.  
  1419.   return (0);
  1420. }
  1421.  
  1422. LONG setcolors (struct ILBMInfo *ilbm,struct ViewPort *vp)
  1423. {
  1424. LONG ncolors;
  1425.  
  1426.   if (! vp) return (CLIENT_ERROR);
  1427.  
  1428.   ncolors = MIN (ilbm->ncolors,vp->ColorMap->Count);
  1429.  
  1430.   if ((! (ilbm->IFFPFlags & IFFPF_NOCOLOR32)) && (ilbm->colorrecord))
  1431.  
  1432.      LoadRGB32 (vp,ilbm->colorrecord);
  1433.  
  1434.   else
  1435.  
  1436.      if (ilbm->colortable) LoadRGB4 (vp,(UWORD *) ilbm->colortable,ncolors);
  1437.  
  1438.   return (NULL);
  1439. }
  1440.  
  1441. /**********  ByteRun1 ***************************************************/
  1442.  
  1443. static BYTE *PutDump (BYTE *dest, int nn)
  1444. {
  1445.   LONG i;
  1446.  
  1447.   PutByte (nn-1);
  1448.  
  1449.   for (i = 0;  i < nn;  i++) PutByte (PackBuffer [i]);
  1450.  
  1451.   return (dest);
  1452. }
  1453.  
  1454. static BYTE *PutRun (BYTE *dest, int nn, int cc)
  1455. {
  1456.   PutByte (-(nn-1));
  1457.  
  1458.   PutByte (cc);
  1459.  
  1460.   return( dest);
  1461. }
  1462.  
  1463. /*----------- packrow --------------------------------------------------*/
  1464.  
  1465. /* Given POINTERS TO POINTERS, packs one row, updating the source and
  1466.  * destination pointers.  RETURNs count of packed bytes. */
  1467.  
  1468. LONG PackRow (BYTE **pSource, BYTE **pDest, LONG rowSize)
  1469. {
  1470. BYTE *source, *dest;
  1471. char c,lastc;
  1472. BOOL mode = DUMP;
  1473. WORD nbuf;       /* number of chars in buffer */
  1474. WORD rstart = 0; /* buffer index current run starts */
  1475.  
  1476.   source = *pSource;
  1477.  
  1478.   dest = *pDest;
  1479.  
  1480.   PackPutSize = 0;
  1481.  
  1482.   PackBuffer [0] = lastc = c = GetByte ();  /* so have valid lastc */
  1483.  
  1484.   nbuf = 1;   rowSize--;    /* since one byte eaten.*/
  1485.  
  1486.   for (;  rowSize;  --rowSize)
  1487.   {
  1488.     PackBuffer [nbuf++] = c = GetByte ();
  1489.  
  1490.     switch (mode)
  1491.     {
  1492.       case DUMP:
  1493.  
  1494.         /* If the buffer is full, write the length byte, then the data */
  1495.         if (nbuf>MaxDat)
  1496.         {
  1497.           OutDump(nbuf-1);
  1498.           PackBuffer[0] = c;
  1499.           nbuf = 1;
  1500.           rstart = 0;
  1501.           break;
  1502.         }
  1503.  
  1504.         if (c == lastc)
  1505.         {
  1506.           if (nbuf-rstart >= MinRun)
  1507.           {
  1508.             if (rstart > 0)
  1509.               OutDump(rstart);
  1510.             mode = RUN;
  1511.           }
  1512.                 else
  1513.             if (rstart == 0)
  1514.               mode = RUN; /* no dump in progress, so can't lose by making these 2 a run.*/
  1515.         }
  1516.         else
  1517.           rstart = nbuf-1;        /* first of run */
  1518.         break;
  1519.  
  1520.       case RUN:
  1521.  
  1522.         if ( (c != lastc)|| ( nbuf-rstart > MaxRun))
  1523.         {
  1524.           /* output run */
  1525.           OutRun(nbuf-1-rstart,lastc);
  1526.           PackBuffer[0] = c;
  1527.           nbuf = 1;
  1528.           rstart = 0;
  1529.           mode = DUMP;
  1530.         }
  1531.         break;
  1532.     }
  1533.  
  1534.     lastc = c;
  1535.   }
  1536.  
  1537.   switch (mode)
  1538.   {
  1539.     case DUMP: OutDump (nbuf);
  1540.  
  1541.                break;
  1542.  
  1543.     case RUN:  OutRun (nbuf-rstart,lastc);
  1544.  
  1545.                break;
  1546.   }
  1547.  
  1548.   *pSource = source;
  1549.  
  1550.   *pDest = dest;
  1551.  
  1552.   return (PackPutSize);
  1553. }
  1554.  
  1555. BOOL UnPackRow (BYTE **pSource, BYTE **pDest, WORD srcBytes0, WORD dstBytes0)
  1556. {
  1557.   register BYTE *source = *pSource;
  1558.   register BYTE *dest   = *pDest;
  1559.   register WORD n;
  1560.   register WORD srcBytes = srcBytes0;
  1561.   register WORD dstBytes = dstBytes0;
  1562.   BOOL error = TRUE;    /* assume error until we make it through the loop */
  1563.   WORD minus128 = -128;  /* get the compiler to generate a CMP.W */
  1564.   register BYTE c;
  1565.  
  1566.   while( dstBytes > 0 )
  1567.   {
  1568.     if ( (srcBytes -= 1) < 0 )
  1569.     {
  1570.       *pSource = source;
  1571.       *pDest = dest;
  1572.       return(error);
  1573.     }
  1574.     n = UGetByte();
  1575.  
  1576.     if (n >= 0)
  1577.     {
  1578.       n += 1;
  1579.       if ( (srcBytes -= n) < 0 )
  1580.       {
  1581.         *pSource = source;
  1582.         *pDest = dest;
  1583.         return(error);
  1584.       }
  1585.       if ( (dstBytes -= n) < 0 )
  1586.       {
  1587.         *pSource = source;
  1588.         *pDest = dest;
  1589.         return(error);
  1590.       }
  1591.       do
  1592.       {
  1593.         UPutByte(UGetByte());
  1594.       } while (--n > 0);
  1595.     }
  1596.     else
  1597.     if (n != minus128)
  1598.     {
  1599.       n = -n + 1;
  1600.       if ( (srcBytes -= 1) < 0 )
  1601.       {
  1602.         *pSource = source;
  1603.         *pDest = dest;
  1604.         return(error);
  1605.       }
  1606.       if ( (dstBytes -= n) < 0 )
  1607.       {
  1608.         *pSource = source;
  1609.         *pDest = dest;
  1610.         return(error);
  1611.       }
  1612.       c = UGetByte();
  1613.       do
  1614.       {
  1615.         UPutByte(c);
  1616.       } while (--n > 0);
  1617.     }
  1618.   }
  1619.   error = FALSE;    /* success! */
  1620.   *pSource = source;
  1621.   *pDest = dest;
  1622.   return(error);
  1623. }
  1624.  
  1625. /*----------------------------------------------------------------------*/
  1626.  
  1627. /* queryilbm
  1628.  *
  1629.  * Passed an initilized ILBMInfo with a not-in-use IFFHandle,
  1630.  *   and a filename,
  1631.  *   will open an ILBM, fill in ilbm->camg and ilbm->bmhd,
  1632.  *   and close the ILBM.
  1633.  *
  1634.  * This allows you to determine if the ILBM is a size and
  1635.  *   type you want to deal with.
  1636.  *
  1637.  * Returns 0 for success or an IFFERR (libraries/iffparse.h)
  1638.  */
  1639.  
  1640. LONG QueryMandPic (struct ILBMInfo *ilbm,struct MandelChunk **ManChk,UBYTE *filename)
  1641. {
  1642. LONG error;
  1643.  
  1644. BitMapHeader *bmhd;
  1645.  
  1646.   if (! (ilbm->ParseInfo.iff)) return (CLIENT_ERROR);
  1647.  
  1648.   error = openifile (&(ilbm->ParseInfo),filename,IFFF_READ);
  1649.  
  1650.   if (! error)
  1651.   {
  1652.      error = parseifile (&(ilbm->ParseInfo),ID_FORM,ID_ILBM,ilbm->ParseInfo.propchks,ilbm->ParseInfo.collectchks,ilbm->ParseInfo.stopchks);
  1653.  
  1654.      if ((! error) || (error == IFFERR_EOC) || (error == IFFERR_EOF))
  1655.      {
  1656.     if (contextis (ilbm->ParseInfo.iff,ID_ILBM,ID_FORM))
  1657.     {
  1658.        if (*ManChk = (struct MandelChunk *) findpropdata (ilbm->ParseInfo.iff,ID_ILBM,ID_MAND))
  1659.        {
  1660.               if (bmhd = (BitMapHeader *) findpropdata (ilbm->ParseInfo.iff,ID_ILBM,ID_BMHD))
  1661.               {
  1662.                  *(&ilbm->Bmhd) = *bmhd;
  1663.  
  1664.                  ilbm->camg = getcamg (ilbm);
  1665.               }
  1666.  
  1667.               else error = NOFILE;
  1668.        }
  1669.  
  1670.        else error = NOMAND;
  1671.     }
  1672.  
  1673.     else error = NOFILE;
  1674.      }
  1675.  
  1676.      closeifile (&(ilbm->ParseInfo));
  1677.   }
  1678.  
  1679.   return (error);
  1680. }
  1681.  
  1682. /* LoadMandPic
  1683.  *
  1684.  * Passed a not-in-use IFFHandle, an initialized ILBMInfo, and filename,
  1685.  *   will load an ILBM into your already opened ilbm->scr, setting up
  1686.  *   ilbm->Bmhd, ilbm->camg, ilbm->colortable, and ilbm->ncolors
  1687.  *   and loading the colors into the screen's viewport
  1688.  *
  1689.  *   Note that ncolors may be more colors than you can LoadRGB4.
  1690.  *   Use MIN(ilbm->ncolors,vp->ColorMap->Count) for color count if
  1691.  *   you change the colors yourself using 1.3/2.0 functions.
  1692.  *
  1693.  * V39 - unless ilbm->IFFPFlags & IFFPF_NOCOLOR32, will do 32-bit
  1694.  *   color load under V39 and higher
  1695.  *
  1696.  * Returns 0 for success or an IFFERR (libraries/iffparse.h)
  1697.  *
  1698.  * NOTE - LoadMandPic () keeps the IFFHandle open so you can copy
  1699.  *   or examine other chunks.  You must call closeifile(iff,ilbm)
  1700.  *   to close the file and deallocate the parsed context
  1701.  *
  1702.  */
  1703.  
  1704. LONG LoadMandPic (struct ILBMInfo *ilbm,UBYTE *filename)
  1705. {
  1706. struct BitMap *TmpBM;
  1707.  
  1708. LONG error;
  1709.  
  1710.   if (! (ilbm->ParseInfo.iff)) return (CLIENT_ERROR);
  1711.  
  1712.   if (! ilbm->scr) return (CLIENT_ERROR);
  1713.  
  1714.   if (! (ilbm->vp)) ilbm->vp = &ilbm->scr->ViewPort;
  1715.  
  1716.   error = openifile (&(ilbm->ParseInfo),filename,IFFF_READ);
  1717.  
  1718.   if (! error)
  1719.   {
  1720.      error = parseifile (&(ilbm->ParseInfo),ID_FORM,ID_ILBM,ilbm->ParseInfo.propchks,ilbm->ParseInfo.collectchks,ilbm->ParseInfo.stopchks);
  1721.  
  1722.      if ((! error) || (error == IFFERR_EOC) || (error == IFFERR_EOF))
  1723.      {
  1724.         if (contextis (ilbm->ParseInfo.iff,ID_ILBM,ID_FORM))
  1725.         {
  1726.            if (GetBitMapAttr (ilbm->wrp->BitMap,BMA_FLAGS) & BMF_STANDARD)
  1727.            {
  1728.               if (! (error = loadbody (ilbm->ParseInfo.iff,ilbm->wrp->BitMap,&ilbm->Bmhd)))
  1729.  
  1730.               if (! (getcolors (ilbm)))
  1731.               {
  1732.                  setcolors (ilbm,ilbm->vp);
  1733.  
  1734.                  freecolors (ilbm);
  1735.               }
  1736.            }
  1737.  
  1738.            else
  1739.            {
  1740.               if (TmpBM = AllocBitMap (ilbm->win->Width,ilbm->win->Height,ilbm->wrp->BitMap->Depth,BMF_INTERLEAVED | BMF_CLEAR | BMF_MINPLANES,NULL))
  1741.               {
  1742.                  if (! (error = loadbody (ilbm->ParseInfo.iff,TmpBM,&ilbm->Bmhd)))
  1743.  
  1744.                     BltBitMapRastPort (TmpBM,ilbm->win->LeftEdge,ilbm->win->TopEdge,ilbm->wrp,ilbm->win->LeftEdge,ilbm->win->TopEdge,ilbm->win->Width,ilbm->win->Height,0xC0);
  1745.  
  1746.                  FreeBitMap (TmpBM);
  1747.  
  1748.                  if (! (getcolors (ilbm)))
  1749.                  {
  1750.                     setcolors (ilbm,ilbm->vp);
  1751.  
  1752.                     freecolors (ilbm);
  1753.                  }
  1754.               }
  1755.            }
  1756.         }
  1757.  
  1758.         else error = NOFILE;
  1759.      }
  1760.  
  1761.      closeifile (&(ilbm->ParseInfo));
  1762.   }
  1763.  
  1764.   return (error);
  1765. }
  1766.  
  1767. LONG SaveMandPic (struct ILBMInfo *ilbm,struct Chunk *chunklist1,struct Chunk *chunklist2,UBYTE *filename)
  1768. {
  1769. struct BitMap *TmpBM;
  1770.  
  1771. Color32 *colortable32;
  1772.  
  1773. UWORD count;
  1774.  
  1775. ULONG modeid;
  1776.  
  1777. LONG error = IFFERR_NOMEM;
  1778.  
  1779.   modeid = GetVPModeID (ilbm->vp);
  1780.  
  1781.   count = ilbm->vp->ColorMap->Count;
  1782.  
  1783.   if (colortable32 = (Color32 *) AllocVec (sizeof (Color32) * count,MEMF_CLEAR))
  1784.   {
  1785.      if (GetBitMapAttr (ilbm->wrp->BitMap,BMA_FLAGS) & BMF_STANDARD)
  1786.      {
  1787.         GetRGB32 (ilbm->vp->ColorMap,0L,count,(ULONG *) colortable32);
  1788.  
  1789.         error = saveilbm (ilbm,ilbm->wrp->BitMap,modeid,ilbm->win->Width,ilbm->win->Height,ilbm->win->Width,ilbm->win->Height,colortable32,count,32,mskNone,0,chunklist1,chunklist2,filename);
  1790.      }
  1791.  
  1792.      else
  1793.      {
  1794.         if (TmpBM = AllocBitMap (ilbm->win->Width,ilbm->win->Height,ilbm->wrp->BitMap->Depth,BMF_INTERLEAVED | BMF_CLEAR | BMF_MINPLANES,NULL))
  1795.         {
  1796.            GetRGB32 (ilbm->vp->ColorMap,0L,count,(ULONG *) colortable32);
  1797.  
  1798.            BltBitMap (ilbm->wrp->BitMap,ilbm->win->LeftEdge,ilbm->win->TopEdge,TmpBM,ilbm->win->LeftEdge,ilbm->win->TopEdge,ilbm->win->Width,ilbm->win->Height,0xC0,0xFF,NULL);
  1799.  
  1800.            error = saveilbm (ilbm,TmpBM,modeid,ilbm->win->Width,ilbm->win->Height,ilbm->win->Width,ilbm->win->Height,colortable32,count,32,mskNone,0,chunklist1,chunklist2,filename);
  1801.  
  1802.            FreeBitMap (TmpBM);
  1803.         }
  1804.      }
  1805.      FreeVec (colortable32);
  1806.   }
  1807.  
  1808.   if (! error) PutDiskObject (filename,&ILBMobject);
  1809.  
  1810.   return (error);
  1811. }
  1812.  
  1813. LONG LoadPalette (struct ILBMInfo *ilbm,UBYTE *filename)
  1814. {
  1815. LONG error;
  1816.  
  1817.   error = openifile (&(ilbm->ParseInfo),filename,IFFF_READ);
  1818.  
  1819.   if (! error)
  1820.   {
  1821.      error = parseifile (&(ilbm->ParseInfo),ID_FORM,ID_ILBM,ilbm->ParseInfo.propchks,ilbm->ParseInfo.collectchks,ilbm->ParseInfo.stopchks);
  1822.  
  1823.      if ((! error) || (error == IFFERR_EOC) || (error == IFFERR_EOF))
  1824.      {
  1825.         if (! (getcolors (ilbm)))
  1826.         {
  1827.            setcolors (ilbm,ilbm->vp);
  1828.  
  1829.            freecolors (ilbm);
  1830.         }
  1831.      }
  1832.  
  1833.      closeifile (&(ilbm->ParseInfo));
  1834.   }
  1835.  
  1836.   return (error);
  1837. }
  1838.  
  1839. LONG SavePalette (struct ILBMInfo *ilbm,struct Chunk *chunklist,UBYTE *filename)
  1840. {
  1841. struct IFFHandle *iff;
  1842.  
  1843. struct Chunk *chunk;
  1844.  
  1845. Color32 *colortable32;
  1846.  
  1847. UWORD ncolors;
  1848.  
  1849. LONG size,error;
  1850.  
  1851. ULONG chunkID;
  1852.  
  1853.   iff = ilbm->ParseInfo.iff;
  1854.  
  1855.   ncolors = ilbm->vp->ColorMap->Count;
  1856.  
  1857.   error = openifile (&(ilbm->ParseInfo),filename,IFFF_WRITE);
  1858.  
  1859.   if (! error)
  1860.   {
  1861.     error = PushChunk (iff,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN);
  1862.  
  1863.     if (colortable32 = (Color32 *) AllocVec (sizeof (Color32) * ncolors,MEMF_CLEAR))
  1864.     {
  1865.        GetRGB32 (ilbm->vp->ColorMap,0L,ncolors,(ULONG *) colortable32);
  1866.  
  1867.        CkErr (putcmap (iff,colortable32,ncolors,32));
  1868.  
  1869.        FreeVec (colortable32);
  1870.     }
  1871.  
  1872.     for (chunk = chunklist; chunk; chunk = chunk->ch_Next)
  1873.     {
  1874.       chunkID = chunk->ch_ID;
  1875.  
  1876.       if ((chunkID != ID_BMHD) && (chunkID != ID_CMAP) && (chunkID != ID_CAMG))
  1877.       {
  1878.         size = chunk->ch_Size == IFFSIZE_UNKNOWN ? strlen (chunk->ch_Data) : chunk->ch_Size;
  1879.  
  1880.         CkErr (PutCk (iff,chunkID,size,chunk->ch_Data));
  1881.       }
  1882.     }
  1883.  
  1884.     CkErr (PopChunk (iff));    /* close out the FORM */
  1885.  
  1886.     closeifile (&(ilbm->ParseInfo));    /* and the file */
  1887.   }
  1888.  
  1889.   return (error);
  1890. }
  1891.